package structures;
import java.io.Serializable;
import java.util.ArrayList;

import Items.Sandwich;
import Items.Water;

/**
 * Spaceship: Holds crew of Passengers, an Inventory of items for use on the ship and on 
 * its passengers, has a pace and rations as well as a Klepton limit for the ship
 * Possesses ability to change all held data.
 * 
 */
@SuppressWarnings("serial")
public class Spaceship implements Serializable{
	private Pace pace;
	private Rations rations;
	private ArrayList<Passenger> plist;
	private int pAlive, pCryo;
	private static int KLEPTON_LIMIT;
	private Inventory playerInventory = new Inventory();
	private double location, lastLocation;
	
	private int enginesBroken;

	private String updateText;
	
	/**
	 * Spaceship Constructor
	 */
	public Spaceship()
	{
		pace = Pace.NORMALLY;
		rations = Rations.SUFFICIENTLY;
		plist = new ArrayList<Passenger>(5);
		pAlive = plist.size();
		pCryo = 0;
		KLEPTON_LIMIT = 100000;
		playerInventory.buildSpaceshipInventory();
		location = 0;
		lastLocation = 0;
		updateText = "You haven't done anything.";
		
		enginesBroken = 0;
	}
	
	/**
	 * Get the number of players alive
	 * @return pAlive
	 */
	public int getpAlive() {
		return pAlive;
	}

	/**
	 * Set the number of players alive
	 * @param pAlive the desired number f players alive
	 */
	public void setpAlive(int pAlive) {
		this.pAlive = pAlive;
	}
	
	/**
	 * Get the number of players in Cryo
	 * @return pCryo
	 */
	public int getpCryo() {
		return pCryo;
	}

	/**
	 * Set the number of players in Cryo
	 * @param pCryo the desired number of players in Cryo
	 */
	public void setpCryo(int pCryo) {
		this.pCryo = pCryo;
	}

	/**
	 * Decrements a food item, a water item, 
	 */
	public void useRations(){
		if(playerInventory.getQuantity(new Sandwich()) > (plist.size() * rations.getRations())){
			playerInventory.removeItem(new Sandwich(), (int)(plist.size() * rations.getRations()));		
			updateText = "The crew ate " + (plist.size() * rations.getRations()) + " sandwiches.";
			for(int i = 0; i < plist.size(); i++){
				plist.get(i).eat(rations.getRations());
			}
		}
		
		else if(playerInventory.getQuantity(new Sandwich()) > 0){
			playerInventory.setQuantity(new Sandwich(), 0);
			updateText = "Your party just ate its last sandwiches!";
			for(int i = 0; i < plist.size(); i++){
				plist.get(i).eat(rations.getRations() - 1);
			}
		}
		
		else{
			updateText = "Your party has nothing to eat!";
		}
	}
	
	
	/**
	 * Use Water, decrease amount in inventory, maintain passenger health
	 */
	public void useWater(){
		if(playerInventory.getQuantity(new Water()) > (plist.size() * rations.getRations())){
			playerInventory.removeItem(new Water(), (int)(plist.size() * rations.getRations()));		
			updateText += "\nThe crew drank " + (plist.size() * rations.getRations()) + " glasses of water.";
			for(int i = 0; i < plist.size(); i++){
				plist.get(i).eat(rations.getRations());
			}
		}
		
		else if(playerInventory.getQuantity(new Water()) > 0){
			playerInventory.setQuantity(new Water(), 0);
			updateText += "\nYour party just drank its last water!";
			for(int i = 0; i < plist.size(); i++){
				plist.get(i).eat(rations.getRations() - 1);
			}
		}
		
		else{
			updateText += "\nYour party has nothing to drink!";
		}
	}
	
	/**
	 * Player Inventory Accessor
	 * @return playerInventory
	 */
	public Inventory getInventory()
	{
		return playerInventory;
	}
	
	/**
	 * Pace Accessor
	 * @return pace
	 */
	public Pace getPace() {
		return pace;
	}

	/**
	 * Pace Mutator
	 * @param pace the intended pace of the ship
	 */
	public void setPace(Pace pace) {
		this.pace = pace;
	}

	/**
	 * Rations Accessor
	 * @return rations
	 */
	public Rations getRations() {
		return rations;
	}

	/**
	 * Rations Mutator
	 * @param rations the intended rations on the ship
	 */
	public void setRations(Rations rations) {
		this.rations = rations;
	}

	/**
	 * Crew Accessor
	 * @return plist
	 */
	public ArrayList<Passenger> getPlist() {
		return plist;
	}

	/**
	 * Crew Accessor
	 * @param plist the new crew of the ship
	 */
	public void setPlist(ArrayList<Passenger> plist) {
		this.plist = plist;
	}

	/**
	 * Klepton Limit Accessor
	 * @return KLEPTON_LIMIT
	 */
	public int getKleptonLimit() {
		return KLEPTON_LIMIT;
	}
	
	/**
	 * Checks if the kleptons currently in the ship plus a potential klepton amount
	 * does not exceed to KLEPTON_LIMIT
	 * @param amount the amount of kleptons that will be added to Inventory
	 * @return true if the inventory has a klepton total less than the limit
	 */
    public boolean checkKleptonLimit(int amount){
        int totalKleptons = playerInventory.calculateKleptons() + amount;
        if (totalKleptons < KLEPTON_LIMIT)
            return true;
        else
            return false;
    }

    /**
     * Moves Spaceship by modifying location based on pace
     */
    public void move() {
    	lastLocation = location;
    	location = location + pace.getPace();
    	updateText = "You moved " + pace.getPace() + " paces along the path.\nYou are now at location " + location + ".";
    	for(Passenger p: plist){
    		double health = p.getHealth();
    		Status s = p.updateStatus(); 
    		p.setHealth(health - pace.getPace() - p.getStatus().healthModifier);
   			//if(p.getStatus() != s)
    		if(p.getStatus() != Status.HEALTHY){
    			updateText += "\n" + p.getName() + p.getStatus().giveReport;
    		}
    	}
    }
    
    /**
     * Set update text
     */
    public void updateUpdateText(){
        if (location == lastLocation)
            updateText = "Your are now at location " + location + ".";
        else
            updateText = "You moved " + (location - lastLocation) + " paces along the path.\nYou are now at location " + location + ".";
    }
    
    /**
     * Update Text accessor
     * @return updateText
     */
    public String getUpdateText() {
    	return updateText;
    }
    
    /**
     * Location Accessor of this Spaceship
     * @return location
     */
    public double getLocation() {
        return location;
    }
    
    /**
     * Location Mutator for this Spaceship
     * @param location
     */
    public void setLocation(double location) { 
        this.location = location;
    }
    
    /**
     * Last Location Mutator
     * @param location
     */
    public void setLastLocation(double location) {
        this.lastLocation = location;
    }
    
    /**
     * Last Location Accessor
     * @return lastLocation
     */
    public double getLastLocation() {
        return lastLocation;
    }
    
    public void fixEngine() {
    	if(enginesBroken > 0)
    		enginesBroken--;
    }
    
    public void breakEngine() { 
    	enginesBroken++;
    }
}
